//============================================================================
// Name        : command_pattern.cpp
// Author      : Tony
// Version     :
// Copyright   : GPLv2
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <vector>
using namespace std;
class Document
{
public:
	Document()
	{
		this->content = "";
	}
	string content;
};

class Command
{
public:
	virtual ~Command(){}
	virtual void execute() = 0;
};

class WriteCommand : public Command
{
public:
	WriteCommand(Document* doc, vector<string>* state)
	{
		this->doc = doc;
		this->state = state;
	}
	virtual void execute()
	{
		string input = "";
		cout<<"input content:"<<endl;
		cin >> input;
		doc->content += input;
		state->push_back(doc->content);
	}
private:
	Document* doc;
	vector<string>* state;
};


class DeleteCommand : public Command
{
public:
	DeleteCommand(Document* doc, vector<string>* state)
	{
		this->doc = doc;
		this->state = state;
	}
	virtual void execute()
	{
		if(doc->content.empty())
		{
			cout<<"no content to delete!"<<endl;
			return;
		}
		doc->content.pop_back();
		state->push_back(doc->content);
	}
private:
	Document* doc;
	vector<string>* state;
};

class UndoCommand : public Command
{
public:
	UndoCommand(Document* doc, vector<string>* state)
	{
		this->doc = doc;
		this->state = state;
	}
	virtual void execute()
	{
		if (state->size() == 1)
		{
			cout<<"no command to undo!"<<endl;
			return;
		}
		state->pop_back();
		doc->content = state->back();

	}
private:
	Document* doc;
	vector<string>* state;
};

int main() {
	Document* doc = new Document();
	vector<string>* state = new vector<string>;
	state->push_back(doc->content);

	int operation;
	cout<<"input operation, 0:exit; 1:write; 2:delete; 3:undo"<<endl;
	cin >> operation;
	while(operation != 0)
	{
		switch(operation)
		{
		case 1:
			WriteCommand(doc, state).execute();
			cout<<"write operation: "<<doc->content<<endl;
			break;
		case 2:
			DeleteCommand(doc, state).execute();
			cout<<"delete operation: "<<doc->content<<endl;
			break;
		case 3:
			UndoCommand(doc, state).execute();
			cout<<"undo operation: "<<doc->content<<endl;
			break;
		default:
			cout<<"invalid input!"<<endl;
			goto end;
			break;
		}
		cout<<"input operation, 0:exit; 1:write; 2:delete; 3:undo"<<endl;
		cin >> operation;
	}
end:
	delete doc;
	delete state;
	return 0;
}
